package br.mia.unifor.onaga.cloud.parser;


import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.List;
import java.util.Scanner;

public class OnagaParser {

	final String FOR_INI = "<for ";
	final String FOR_FIM = "</for>";
	InputStream in ;

	public static void main(String... aArgs) throws IOException {
		OnagaParser parser = new OnagaParser(new FileInputStream("C:\\Temp\\template.yml"));
		parser.processLineByLine();
		log("Done.");
	}

	/**
	 * Constructor.
	 * 
	 * @param aFileName
	 *            full name of an existing, readable file.
	 */
	public OnagaParser(InputStream in) {
		this.in = in;
	}

	/** Template method that calls {@link #processLine(String)}. 
	 * @throws IOException */
	public InputStream processLineByLine() throws IOException {
		// Note that FileReader is used, not File, since File is not Closeable
		File file = new File(System.currentTimeMillis()+".tmp");
		FileWriter wrt = new FileWriter(file);
		Scanner scanner = new Scanner(in);
		
		Deque<String> pilha = new ArrayDeque<String>();
		
		List<String> toWrite = null;

		try {
			// first use a Scanner to get each line
			int index = 0;
			while (scanner.hasNextLine()) {
				String line = scanner.nextLine();
				if (-1 != (index = line.indexOf(FOR_INI))) {

					pilha.add(line);
				} else if (-1 != (index = line.indexOf(FOR_FIM))) {
					if(toWrite != null){
						executeCommand(pilha, FOR_INI).addAll(toWrite);
					}
					toWrite = executeCommand(pilha, FOR_INI);

				} else if (pilha.size() > 0) {
					pilha.add(line);
				} else{
					if(toWrite != null){
						for (String string : toWrite) {
							wrt.write(string+"\n");
						}
						toWrite = null;
					}
					wrt.write(line+"\n");
				}
			}
			if(toWrite != null){
				for (String string : toWrite) {
					wrt.write(string+"\n");
				}
				toWrite = null;
			}
			
			
		} finally {
			scanner.close();
			wrt.close();
			
		}
		log(file.getAbsolutePath());
		return new FileInputStream(file);
	}

	protected List<String> executeCommand(Deque<String> deque, String command) {
		List<String> list = new ArrayList<String>();
		String line = deque.removeLast();

		int index = line.indexOf(command);

		while (-1 == index) {
			list.add(line);
			line = deque.removeLast();
			index = line.indexOf(command);
		}
		list.add(line);

		if (-1 != (index = line.indexOf(FOR_INI))) {
			return executeFor(list);
		}
		
		return null;
	}

	protected List<String> executeFor(List<String> list) {
		log(list);
		Scanner scanner = new Scanner(list.get(list.size() - 1));
		scanner.useDelimiter("=");
		
		List<String> retorno = new ArrayList();

		String ITEMS = "items";
		String VAR = "var";
		String COUNT = "count";
		
		String[] items = null;
		String var = "item";
		int count = 0;
		String auxValue = null;
		
		while(scanner.hasNext()){
			String value = null;
			if(auxValue == null)
				value = scanner.next();
			else
				value = auxValue;
			
			auxValue = scanner.next();
			if(value.indexOf(ITEMS) != -1){
				
				items = betweenQuotationMarks(auxValue).split(",");
			}else if(value.indexOf(VAR) != -1){
				
				var = betweenQuotationMarks(auxValue);
			}else if(value.indexOf(COUNT) != -1){
				
				count = new Integer(betweenQuotationMarks(auxValue));
			}
		}
		
		for (String item : items) {
			for (int i = list.size()-2; i >= 0; i--) {
				String linha = list.get(i);
				
				
				int index = linha.indexOf("$[");
				String strParsed = new String(linha);
				while(index != -1){
					int indexEnd = strParsed.indexOf("]");
					String method = strParsed.substring(index+"$[".length(), indexEnd);
					
					String value = null;
					if(method.equals(var)){
						value = item.trim();
					}else if(method.equals(COUNT)){
						value = count+"";
					}
					strParsed = strParsed.substring(0, index) + value.toString() +strParsed.substring(indexEnd+1);
					
					index = strParsed.indexOf("$[");
				}
				
				retorno.add(strParsed);
			}
			count++;
		}

		return retorno;
	}
	
	
	
	protected String betweenQuotationMarks(String value){
		Scanner scanner = new Scanner(value);
		scanner.useDelimiter("\"");
		
		return scanner.next();
	}

	protected void processForIni(String aLine) {
		log("for encontrado!!.");
	}

	private static void log(Object aObject) {
		System.out.println(String.valueOf(aObject));
	}

	private String quote(String aText) {
		String QUOTE = "'";
		return QUOTE + aText + QUOTE;
	}
}